﻿namespace My.Hydrator.Conventions
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public class ListTypeConvention : BaseTypeConvention, IListTypeConvention
    {
        private readonly int numberOfElementsToGenerate;

        private readonly Type genericType;

        private readonly ITypeConvention genericTypeConvention;

        public ListTypeConvention(Type genericType)
            : this(genericType, 10)
        {
        }

        public ListTypeConvention(Type genericType, int numberOfElementsToGenerate)
        {
            this.numberOfElementsToGenerate = numberOfElementsToGenerate;
            this.genericType = genericType;
            this.genericTypeConvention = this.GetConvention(this.genericType);
        }

        public ListTypeConvention(ITypeConvention genericTypeConvention)
            : this(genericTypeConvention.Type, genericTypeConvention, 10)
        {
        }

        public ListTypeConvention(ITypeConvention genericTypeConvention, int numberOfElementsToGenerate)
            : this(genericTypeConvention.Type, genericTypeConvention, numberOfElementsToGenerate)
        {
        }

        protected ListTypeConvention(Type genericType, ITypeConvention genericTypeConvention, int numberOfElementsToGenerate)
        {
            this.numberOfElementsToGenerate = numberOfElementsToGenerate;
            this.genericType = genericType;
            this.genericTypeConvention = genericTypeConvention;
        }

        public virtual Type Type
        {
            get { return typeof(List<>).MakeGenericType(this.genericType); }
        }

        public virtual object GenerateValue(object[] customAttributes)
        {
            this.GetAttributes(customAttributes);

            var result = Activator.CreateInstance(this.Type) as IList;

            if (this.genericTypeConvention != null)
            {
                for (int i = 0; i < this.numberOfElementsToGenerate; i++)
                {
                    result.Add(this.genericTypeConvention.GenerateValue(customAttributes));
                }
            }

            return result;
        }
    }
}
